<template>
  <div class="yaml-diff-wrapper">
    <div class="diff-header">
      <div class="version-info">
        <span class="version-label old">版本 {{ oldVersion }}</span>
        <span class="version-separator">vs</span>
        <span class="version-label new">版本 {{ newVersion }}</span>
      </div>
    </div>
    <div class="diff-content" ref="diffContent">
      <pre v-html="diffHtml"></pre>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, watch } from 'vue'
import { diffLines } from 'diff'

const props = defineProps({
  oldContent: {
    type: String,
    default: ''
  },
  newContent: {
    type: String,
    default: ''
  },
  oldVersion: {
    type: Number,
    default: 1
  },
  newVersion: {
    type: Number,
    default: 2
  }
})

const diffContent = ref(null)

const diffHtml = computed(() => {
  if (!props.oldContent || !props.newContent) {
    return '<span class="diff-empty">无对比内容</span>'
  }

  const diff = diffLines(props.oldContent, props.newContent)
  let html = ''

  diff.forEach((part) => {
    const lines = part.value.split('\n')
    // 移除最后一个空行
    if (lines[lines.length - 1] === '') {
      lines.pop()
    }

    lines.forEach((line) => {
      if (part.added) {
        html += `<div class="diff-line added"><span class="line-marker">+</span><span class="line-content">${escapeHtml(line)}</span></div>`
      } else if (part.removed) {
        html += `<div class="diff-line removed"><span class="line-marker">-</span><span class="line-content">${escapeHtml(line)}</span></div>`
      } else {
        html += `<div class="diff-line unchanged"><span class="line-marker"> </span><span class="line-content">${escapeHtml(line)}</span></div>`
      }
    })
  })

  return html
})

const escapeHtml = (text) => {
  const map = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#039;'
  }
  return text.replace(/[&<>"']/g, (m) => map[m])
}

watch(() => [props.oldContent, props.newContent], () => {
  // 当内容变化时，滚动到顶部
  if (diffContent.value) {
    diffContent.value.scrollTop = 0
  }
})
</script>

<style lang="scss" scoped>
.yaml-diff-wrapper {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  overflow: hidden;

  .diff-header {
    background: #f5f7fa;
    padding: 12px 16px;
    border-bottom: 1px solid #dcdfe6;

    .version-info {
      display: flex;
      align-items: center;
      gap: 12px;
      font-size: 14px;

      .version-label {
        padding: 4px 12px;
        border-radius: 4px;
        font-weight: 500;

        &.old {
          background: #fef0f0;
          color: #f56c6c;
        }

        &.new {
          background: #f0f9ff;
          color: #409eff;
        }
      }

      .version-separator {
        color: #909399;
        font-weight: bold;
      }
    }
  }

  .diff-content {
    flex: 1;
    overflow: auto;
    background: #ffffff;

    pre {
      margin: 0;
      padding: 0;
      font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;
      font-size: 13px;
      line-height: 1.6;

      :deep(.diff-empty) {
        display: block;
        padding: 20px;
        text-align: center;
        color: #909399;
      }

      :deep(.diff-line) {
        display: flex;
        padding: 2px 0;
        margin: 0;

        .line-marker {
          display: inline-block;
          width: 30px;
          text-align: center;
          flex-shrink: 0;
          user-select: none;
          font-weight: bold;
        }

        .line-content {
          flex: 1;
          padding-left: 8px;
          white-space: pre;
          word-break: break-all;
        }

        &.added {
          background-color: #e6ffec;
          color: #00a870;

          .line-marker {
            background-color: #d0f5dd;
          }
        }

        &.removed {
          background-color: #ffebe9;
          color: #d73a49;

          .line-marker {
            background-color: #ffdce0;
          }
        }

        &.unchanged {
          color: #24292e;

          .line-marker {
            color: #d1d5da;
          }
        }

        &:hover {
          background-color: rgba(0, 0, 0, 0.03);
        }
      }
    }
  }
}
</style>
